#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <string>
#define COMMAND_SIZE 1024
#define FORMAT "[%s@%s %s]#"

#define NONE_REDIR 0
#define INPUT_REDIE 1
#define OUTPUT_REDIR 2
#define APPEND_REDIR 3
//全局数据
#define MAXARGC 128
std::string filename;
int redir;
char*g_argv[MAXARGC];
int g_argc=0;
const char*GetUsrName()
{
    const char*UsrName=getenv("USER");
    return UsrName==NULL?"None":UsrName;
}

const char*GetHostName()
{
    const char*HostName=getenv("HOSTNAME");
    return HostName==NULL?"None":HostName;
}

const char*GetPwd()
{
    const char*Pwd=getenv("PWD");
    return Pwd==NULL?"None":Pwd;
}

void PrintCommandPrompt()
{
    char Prompt[COMMAND_SIZE];
    snprintf(Prompt,sizeof(Prompt),FORMAT,GetUsrName(),GetHostName(),GetPwd());
    printf("%s",Prompt);
    fflush(stdout);
}

bool GetCommandLine(char*out,int size)
{
    char* c=fgets(out,size,stdin);
    if(c==NULL)return false;
    out[strlen(out)-1]=0;  //去掉\n
    if(!strlen(out))return false;
    else return true;
}

void TrimSpace(char cmd[],int &index)
{
    while(cmd[index]==' ')index++;
}

void RedirCheck(char cmd[])
{
    redir=NONE_REDIR;
    int start=0,end=strlen(cmd)-1;
    filename.clear();
    while(start<end)
    {
        if(cmd[end]=='<')
        {
            redir=INPUT_REDIE;
            cmd[end++]=0;
            TrimSpace(cmd,end);
            filename=cmd+end;
            break;
        }
        else if(cmd[end]=='>')
        {
            if(cmd[end-1]=='>')
            {
                //>>
                cmd[end-1]=0;
                cmd[end++]=0;
                redir=APPEND_REDIR;
            }
            else {
                redir=OUTPUT_REDIR;
                cmd[end++]=0;
            }
            TrimSpace(cmd,end);
            filename=cmd+end;
            break;
        }
        end--;
    }
}

bool CommandParse(char *commandline)
{
#define SEP " "
    g_argc=0;
    g_argv[g_argc++]=strtok(commandline,SEP);
    while(g_argv[g_argc++]=strtok(nullptr,SEP));
    g_argc--;
    return true;
}

void PrintArgv()
{
    for(int i=0;i<g_argc;i++)
    {
        printf("argv[%d]:%s\n",i,g_argv[i]);
    }
    printf("argc:%d\n",g_argc);
}

int Execute()
{
        pid_t id=fork();
        if(id==0)
        {
            //重定向
            if(redir==INPUT_REDIE)
            {
                int fd=open(filename.c_str(),O_RDONLY);
                dup2(fd,0);
                close(fd);
            }
            else if(redir==OUTPUT_REDIR)
            {
                int fd=open(filename.c_str(),O_WRONLY|O_CREAT|O_TRUNC,0666);
                dup2(fd,1);
                close(fd);
            }
            else if(redir==APPEND_REDIR){
                int fd=open(filename.c_str(),O_WRONLY|O_CREAT|O_APPEND,0666);
                dup2(fd,1);
                close(fd);
            }
            execvp(g_argv[0],g_argv);
            exit(1);
        }
        waitpid(id,nullptr,0);
        return 0;
}

int main()
{
    while(1)
    {
        //1.打印命令行提示符
        PrintCommandPrompt();
        //2.读取命令行输入
        char cmdline[COMMAND_SIZE];
        if((!GetCommandLine(cmdline,sizeof(cmdline))))
            continue;
        //分析重定向
        RedirCheck(cmdline);
        //3.解析命令行输入
        CommandParse(cmdline);
        //4.执行命令
        Execute();
        
    }
   return 0;
}
